package cn.good.yan.service.t2;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 2. CompletableFuture 定义操作 - 异步任务
 * 异步回掉 - 代码编排  有这些方法：whenComplete  exceptionally thenApply handle thenRun
 * 如：后面加 Async方法的  thenApplyAsync，如果使用 线程池，第一个任务使用自己的线程池，第二个任务使用ForkJoin线程池
 *
 * @author shengren.yan
 * @create 2024-03-25
 */
public class CompletableFuture5 {

    // 异步回调 - CompletableFuture，
    // whenComplete （上面线程执行完，再执行这里, 可以手动处理异常）
    // exceptionally（有异常会执行这里，有异常执行这里逻辑） - 有返回值
    // thenApply    （上面线程执行完，再执行这里, 任务出现异常就不会进入 thenApply 方法里 ，不能处理异常） - 有返回值
    // handle       （上面线程执行完，再执行这里, 任务出现异常也会进入handle ，可以处理异常） - 有返回值
    // thenRun      （上面线程执行完，再执行这里）
    public static void main(String[] args) {
        // 线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(3);
        // 案例1 ：thenApply
//        CompletableFuture.supplyAsync(() -> {
//            try {
//                TimeUnit.SECONDS.sleep(1);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println("逻辑1 -- 执行");
//            return 1;
//        }, threadPool).thenApply((f) -> {
//            // 上面的线程，执行完，执行这里逻辑, 任务出现异常就不会进入 thenApply 方法里 / 有返回值
//            // 这里有异常，逻辑3这里就不会执行
//            int i = 10 / 0;
//            System.out.println("逻辑2 -- 执行");
//            return f + 2;
//        }).thenApply((f) -> {
//            System.out.println("逻辑3 -- 执行");
//            return f + 3;
//        }).whenComplete((v, e) -> {
//            // 上面的线程，执行完，执行这里逻辑，这里手动处理异常，/ 没有返回值
//            System.out.println("逻辑4 -- 开始计算");
//            if (e == null) {
//                System.out.println("计算结果： " + v);
//            }
//        }).exceptionally(e -> {
//            // 上面的线程，执行完，有异常执行这里逻辑，/ 有返回值
//            e.printStackTrace();
//            System.out.println("【exceptionally】" + "异常情况：" + e.getCause() + "\t" + e.getMessage());
//            return null;
//        });

        System.out.println("----------------");

        // 案例2 ：handle
//        CompletableFuture.supplyAsync(() -> {
//            try {
//                TimeUnit.SECONDS.sleep(1);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println("逻辑1 -- 执行");
//            return 1;
//        }, threadPool).handle((f, e) -> {
//            // 上面的线程，执行完，执行这里逻辑, 任务出现异常也会进入handle 方法里 / 有返回值
//            // 这里有异常，逻辑3这里也会执行
//            int i = 10 / 0;
//            System.out.println("逻辑2 -- 执行");
//            return f + 2;
//        }).handle((f, e) -> {
//            System.out.println("逻辑3 -- 执行");
//            return f + 3;
//        }).whenComplete((v, e) -> {
//            // 上面的线程，执行完，执行这里逻辑，这里手动处理异常，/ 没有返回值
//            System.out.println("逻辑4 -- 开始计算");
//            if (e == null) {
//                System.out.println("计算结果： " + v);
//            }
//        }).exceptionally(e -> {
//            // 上面的线程，执行完，有异常执行这里逻辑，/ 有返回值
//            e.printStackTrace();
//            System.out.println("【exceptionally】" + "异常情况：" + e.getCause() + "\t" + e.getMessage());
//            return null;
//        });

        System.out.println("----------------");
        // 案例3 ：thenRun 【A 执行完，执行B， B不需要A的返回值 】
//        CompletableFuture.supplyAsync(() -> {
//            System.out.println("A 逻辑1 -- 执行");
//            return 1;
//        }).thenRun(() -> {
//            System.out.println("B 逻辑2 -- 执行");
//        }).join();

        System.out.println("----------------");
        // 案例4 ：thenAccept 【A 执行完，执行B， B可以接受A的参数，无返回值 】
//        CompletableFuture.supplyAsync(() -> {
//            System.out.println("A 逻辑1 -- 执行");
//            return 1;
//        }).thenAccept((f) -> {
//            System.out.println("B 逻辑2 -- 执行" + f);
//        }).join();

        System.out.println("----------------");
        // 案例5 ：thenApply 【A 执行完，执行B， B可以接受A的参数，有返回值 】
        Integer join = CompletableFuture.supplyAsync(() -> {
            System.out.println("A 逻辑1 -- 执行");
            return 1;
        }).thenApply((f) -> {
            System.out.println("B 逻辑2 -- 执行" + f);
            return f;
        }).join();
        System.out.println("返回值:" + join);
        System.out.println(Thread.currentThread().getName() + "----主线程先去忙其它任务");
        threadPool.shutdown();

    }

}

